package smartlifev30.com.sdk.net.baiwei;

import android.annotation.SuppressLint;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.Log;

import java.io.IOException;

import smartlifev30.com.sdk.BaseResponse;
import smartlifev30.com.sdk.BuildConfig;
import smartlifev30.com.sdk.net.core.IClient;
import smartlifev30.com.sdk.util.JsonUtil;

import static smartlifev30.com.sdk.net.core.ConnectStatus.CONNECT_FAILED;
import static smartlifev30.com.sdk.net.core.ConnectStatus.CONNECT_SUCCEED;

/**
 * {@link #init(Context, String, int)}
 * {@link #setHostAndPort(String, int)}
 * {@link #setUserAndToken(String, String)}
 *
 * @author tys
 * @date 2018/8/12
 */

public class NetManager {


    /**
     * 1.服务器token，登陆服务器成功后设置{@link #setUserAndToken(String, String)},用于心跳
     * 2.内网时,登录网关的用户名
     */
    protected static String token;

    /**
     * 1.登陆服务器的用户名，登陆服务器成功后设置{@link #setUserAndToken(String, String)},用于心跳
     * 2.内网时,登录网关的用户名
     */
    protected static String userName;

    /**
     * 连接ip地址, 为空时使用配置值
     */
    private static String host;

    /**
     * 连接的端口,为空时使用配置值
     */
    private static int port;

    @SuppressLint("StaticFieldLeak")
    private static NetManager instance;
    private static IClient<String, String> mClient;
    private Context context;


    public static NetManager getInstance() {
        if (instance == null) {
            synchronized (NetManager.class) {
                if (instance == null) {
                    instance = new NetManager();
                }
            }
        }
        return instance;
    }

    /**
     * 网络设置初始化
     * {@link #setHostAndPort(String, int)}
     *
     * @param context
     * @param host    连接的IP地址。null则使用配置的默认地址
     * @param port    连接端口。 null则使用配置的默认地址
     */
    public void init(@NonNull Context context, @Nullable String host, @Nullable int port) {
        this.context = context.getApplicationContext();
        NetManager.host = host;
        NetManager.port = port;
    }

    public IClient<String, String> getClient() {
        if (NetManager.mClient == null) {
            NetManager.mClient = getDefaultClient();
        }
        return NetManager.mClient;
    }

    /**
     * 设置client
     *
     * @param client
     */
    public void setClient(IClient<String, String> client) {
        if (mClient != null) {
            try {
                mClient.disConnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        NetManager.mClient = client;
    }

    /**
     * 登陆服务器成功后调用,用于心跳
     *
     * @param userName 账号
     * @param token    服务器token
     */
    public void setUserAndToken(String userName, String token) {
        NetManager.userName = userName;
        NetManager.token = token;
    }

    /**
     * 设置连接的ip和端口
     *
     * @param host ip
     * @param port 端口
     */
    public void setHostAndPort(String host, int port) {
        NetManager.host = host;
        NetManager.port = port;
    }


    private IClient<String, String> getDefaultClient() {
        Client client = new Client.Builder()
                .writeTimeOut(60)
                .build();
        return client;
    }


    /**
     * 建立连接, netty不存在IoException
     *
     * @param l
     */
    public void connect(@NonNull String host, @NonNull Integer port, IClient.ConnectListen l) {
        try {
            getClient().connect(host, port, l);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 主动断开连接,(netty 的线程回收) netty不存在IoException
     */
    public void disConnect() {
        try {
            getClient().disConnect();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发生消息
     *
     * @param jsonStr 发生消息的内容. 在{@link Client#encoder}中进行协议的组装
     */
    public void sendMessage(String jsonStr) {
        try {
            final IClient<String, String> client = getClient();
            if (client.getConnectStatus() == CONNECT_FAILED) {
                int currentNetStatus = getCurrentNetStatus(context);
                if (currentNetStatus != ConnectivityManager.TYPE_WIFI &&
                        currentNetStatus != ConnectivityManager.TYPE_MOBILE) {
                    //没网 提前移除, 触发超时回调
                    BaseResponse baseResponse = JsonUtil.toObject(jsonStr, BaseResponse.class);
                    BaseResponseListen.removeEarly(baseResponse.msg_id, "网络不可用");
                } else {
                    //未设置ip和端口则使用配置的默认值
                    if (TextUtils.isEmpty(host) || port <= 0) {
                        host = BuildConfig.IP_DEFAULT;
                        port = BuildConfig.PORT_DEFAULT;
                    }
                    client.connect(host, port, new IClient.ConnectListen() {
                        @Override
                        public void onSuccess() {
                            try {
                                client.send(jsonStr);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }

                        @Override
                        public void onFailed(Throwable e) {
                            Log.e("0-0-", e.toString());
                        }
                    });
                }
            } else if (client.getConnectStatus() == CONNECT_SUCCEED) {
                client.send(jsonStr);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private int getCurrentNetStatus(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm != null) {
            NetworkInfo activeNetworkInfo = cm.getActiveNetworkInfo();
            if (activeNetworkInfo != null && activeNetworkInfo.isConnected()) {
                return activeNetworkInfo.getType();
            }
        }
        return -1;
    }

}
